# vim: set ft=make ts=8 sw=8 noet :

# Set this to your Ewdk build environment. You most likely
# have to create a new one (see the ifeq's in this Makefile)
# to get the pathes right. You also should add a ms-cl-$(BUILD_ENV)
# wrapper script to call the Microsoft C compiler (see the VC variable).
#
# Please use your initials to name the build env if you want to
# commit your changes upstream.
#
# For now run make copy in the windrbd root directory whenever you
# change this Makefile or the ms-cl*.cmd wrappers.
#
# Don't change default here, put it into your .bashrc instead:
# (like export BUILD_ENV=blub)
#
BUILD_ENV ?= jt-server2016

# TODO: unset this for production releases.
KMALLOC_DEBUG = 1
# BIO_REF_DEBUG = 1

ifeq ($(BUILD_ENV),jt-win7)
export EWDK_BASE := c:\\Ewdk
EWDK_KIT := $(EWDK_BASE)\\Program Files\\Windows Kits\\10
EWDK_VERSION := 10.0.15063.0
EWDK_BIN := $(EWDK_KIT)\\bin\\x86

# Name of the pfx file (without extension)
KEY = linbit-2019
PASSWD = ""

WINDRBD_SOURCE = Y:\\windrbd
DRBD_UTILS_SOURCE = Y:\\drbd-utils-windows
endif

# My diskless WinDRBD sysroot machine :)

ifeq ($(BUILD_ENV),jt-diskless-windrbd-sysroot)
export EWDK_BASE := d:
EWDK_KIT := $(EWDK_BASE)\\Program Files\\Windows Kits\\10
EWDK_VERSION := 10.0.17763.0 # TODO: ?
EWDK_BIN := $(EWDK_KIT)\\bin\\$(EWDK_VERSION)\\x86

# Name of the pfx file (without extension)
KEY = linbit-ha
PASSWD = ""

WINDRBD_SOURCE = Y:\\windrbd
DRBD_UTILS_SOURCE = Y:\\drbd-utils-windows
endif

ifeq ($(BUILD_ENV),jt-win10)
export EWDK_BASE := e:
EWDK_KIT := $(EWDK_BASE)\\Program Files\\Windows Kits\\10
EWDK_VERSION := 10.0.17763.0
EWDK_BIN := $(EWDK_KIT)\\bin\\$(EWDK_VERSION)\\x86

# Name of the pfx file (without extension)
KEY = linbit-2019
PASSWD = ""

WINDRBD_SOURCE = Y:\\windrbd
DRBD_UTILS_SOURCE = Y:\\drbd-utils-windows
endif

ifeq ($(BUILD_ENV),jt-win10-32bit)
export EWDK_BASE := d:
EWDK_KIT := $(EWDK_BASE)\\Program Files\\Windows Kits\\10
EWDK_VERSION := 10.0.17763.0
EWDK_BIN := $(EWDK_KIT)\\bin\\$(EWDK_VERSION)\\x86

# Name of the pfx file (without extension)
KEY = linbit-ha
PASSWD = ""

WINDRBD_SOURCE = Y:\\windrbd
DRBD_UTILS_SOURCE = Y:\\drbd-utils-windows
endif

ifeq ($(BUILD_ENV),jt-server2016)
export EWDK_BASE := c:\\Ewdk
EWDK_KIT := $(EWDK_BASE)\\Program Files\\Windows Kits\\10
EWDK_VERSION := 10.0.17763.0
EWDK_BIN := $(EWDK_KIT)\\bin\\$(EWDK_VERSION)\\x86

# Name of the pfx file (without extension)
KEY = linbit-ha
PASSWD = ""

WINDRBD_SOURCE = Y:\\windrbd
DRBD_UTILS_SOURCE = Y:\\drbd-utils-windows
endif

ifeq ($(BUILD_ENV),jt-win10ent-2020)
export EWDK_BASE := e:
EWDK_KIT := $(EWDK_BASE)\\Program Files\\Windows Kits\\10
EWDK_VERSION := 10.0.19041.0
EWDK_BIN := $(EWDK_KIT)\\bin\\$(EWDK_VERSION)\\x86

# Name of the pfx file (without extension)
KEY = linbit-2019
PASSWD = ""

WINDRBD_SOURCE = Y:\\windrbd
DRBD_UTILS_SOURCE = Y:\\drbd-utils-windows
endif

ifndef EWDK_VERSION
$(error EWDK_BASE not set. Please edit Makefile to make it know about your ewdk installation.)
endif

ifdef R
EXTRA_VERSION ?= -signed
else
EXTRA_VERSION ?=
endif

EWDK_INC := $(EWDK_KIT)\\Include
EWDK_LIB := $(EWDK_KIT)\\Lib
VC := /cygdrive/c/Windows/System32/cmd.exe /c ms-cl-$(BUILD_ENV).cmd
CERTMGR := "$(EWDK_BIN)/certmgr.exe"

# /a      for debugging output


# CL.exe takes (AND RETURNS) forward slashes; that makes navigating an error output easy.
WIN_INCLUDE_DIRS += "-I$(EWDK_INC)\\$(EWDK_VERSION)\\shared"
WIN_INCLUDE_DIRS += "-I$(EWDK_INC)\\$(EWDK_VERSION)\\km"
WIN_INCLUDE_DIRS += "-I$(EWDK_INC)\\$(EWDK_VERSION)\\km\\crt"
WIN_INCLUDE_DIRS += "-I$(EWDK_INC)\\$(EWDK_VERSION)\\um"

WIN_DEF_INCLUDES += /FI"$(EWDK_INC)/$(EWDK_VERSION)\\shared\\warning.h"
# include that file

WIN_CFLAGS += /c /nologo /W4 
WIN_CFLAGS += /Zi # /Zi gives us a PDB file; without that we'd get debug information in the .obj file instead
WIN_CFLAGS += /WX # warnings == errors
WIN_CFLAGS += /Wv:18 # disable hides previous local declaration
WIN_CFLAGS += /O2 # optimize for speed
WIN_CFLAGS += /Oi # enable intrinsic functions
WIN_CFLAGS += /Oy- # enable frame pointer omission
# C_DEFINES += -D _X86_=1 -D i386=1 # 32bit
C_DEFINES += -D _WIN64 -D _AMD64_ -D AMD64 -D _M_AMD64 # 64bit
C_DEFINES += -D STD_CALL -D DEPRECATE_DDK_FUNCTIONS=1 -D MSC_NOOPT -D _WIN32_WINNT=0x0601 -D WINVER=0x0601 -D WINNT=1 -D NTDDI_VERSION=0x06010000 -D KMDF_VERSION_MAJOR=1 -D KMDF_VERSION_MINOR=15 
# C_DEFINES += -D DBG=1
ifdef R
C_DEFINES += -D RELEASE=1
endif
ifdef KMALLOC_DEBUG
C_DEFINES += -D KMALLOC_DEBUG=1
endif
ifdef BIO_REF_DEBUG
C_DEFINES += -D BIO_REF_DEBUG=1
endif

WIN_CFLAGS += /GF /Gm- /Zp8 /GS /Gy 
# /fp:precise  # precise - "precise" floating-point model; results are predictable
WIN_CFLAGS += /Zc:wchar_t- /Zc:forScope /Zc:inline /GR- 
# On x64, there's only one calling convention. https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
# WIN_CFLAGS += /Gz # __stdcall calling convention  -- is default
# WIN_CFLAGS += /Gr # __fastcall calling convention -- is what we want for linux compat
WIN_CFLAGS += /wd4748 /wd4603 /wd4627 /wd4986 /wd4987 /wd4996 
WIN_CFLAGS += /analyze- /errorReport:queue /kernel -cbstring /d1import_no_registry /d2AllowCompatibleILVersions /d2Zi+ 
C_DEFINES += -D __KERNEL__=1
C_DEFINES += -D __BYTE_ORDER=1 -D __LITTLE_ENDIAN=1 -D __LITTLE_ENDIAN_BITFIELD

# WIN_CFLAGS += /Ze # Microsoft extensions - eg. nameless struct/union. Not enabled because
#   The /Ze option is deprecated because its behavior is on by default. We recommend you use the /Zc (Conformance) compiler options to control specific language extension features.
# but there's no setting for that.
WIN_CFLAGS += /wd4201

# drbd-headers\drbd_protocol.h(466): warning C4200: nonstandard extension used: zero-sized array in struct/union
WIN_CFLAGS += /wd4200

WIN_INCLUDE_DIRS += -I"..\\..\\windrbd\\include"
WIN_INCLUDE_DIRS += -I"."
WIN_INCLUDE_DIRS += -I".\\drbd-headers"

WIN_CFLAGS += $(WIN_INCLUDE_DIRS)
ifeq (V,1)
WIN_CFLAGS += /showIncludes 
endif

C_DEFINES += -D _WIN64=1
C_DEFINES += -D COMPAT_HAVE_BOOL_TYPE=1 # for "typedef bool" in drbd/linux/lru_cache.h
# C_DEFINES += -D _AMD64_=1

C_DEFINES += -D CONFIG_KREF_DEBUG=1

WIN_CFLAGS += $(C_DEFINES)

# How to calculate the debug name
fPDB = $(patsubst %.c,%.pdb,$(1))

WIN_LDFLAGS += /link # must be first!
# Was:
WIN_LDFLAGS += /DRIVER:WDM /NODEFAULTLIB /ENTRY:DriverEntry
# However this prevents the driver from being unloaded. We try
# this now:
# WIN_LDFLAGS += /DRIVER /SUBSYSTEM:WINDOWS /NODEFAULTLIB /ENTRY:DriverEntry
WIN_LDFLAGS += "/LIBPATH:$(EWDK_LIB)/win7/km/x64/"
WIN_LDFLAGS += "/LIBPATH:$(EWDK_LIB)/$(EWDK_VERSION)/km/x64/"
WIN_LDFLAGS += /DEBUG:FULL
WIN_LINK_INPUT += wdm.lib
WIN_LINK_INPUT += ntoskrnl.lib
WIN_LINK_INPUT += bufferoverflowfastfailk.lib # for __security_check_cookie
WIN_LINK_INPUT += netio.lib
WIN_LINK_INPUT += wdmsec.lib
WIN_LINK_INPUT += "$(EWDK_LIB)/win8/km/x64/aux_klib.lib"
# WIN_LINK_INPUT += setupapi.lib

DRBD_FILES = drbd_buildtag.c drbd_bitmap.c drbd_proc.c
DRBD_FILES += drbd_sender.c drbd_receiver.c drbd_req.c drbd_actlog.c
DRBD_FILES += lru_cache.c drbd_main.c drbd_strings.c drbd_nl.c
DRBD_FILES += drbd_interval.c drbd_state.c drbd_kref_debug.c
DRBD_FILES += drbd_nla.c drbd_transport.c drbd_transport_tcp.c kref_debug.c

WINDRBD_SRCDIR = ../../windrbd/src

WINDRBD_FILES = $(WINDRBD_SRCDIR)/Attr.c $(WINDRBD_SRCDIR)/disp.c $(WINDRBD_SRCDIR)/drbd_windows.c $(WINDRBD_SRCDIR)/hweight.c \
		$(WINDRBD_SRCDIR)/idr.c $(WINDRBD_SRCDIR)/kmalloc_debug.c $(WINDRBD_SRCDIR)/mempool.c $(WINDRBD_SRCDIR)/printk-to-syslog.c \
		$(WINDRBD_SRCDIR)/rbtree.c $(WINDRBD_SRCDIR)/seq_file.c $(WINDRBD_SRCDIR)/slab.c $(WINDRBD_SRCDIR)/util.c $(WINDRBD_SRCDIR)/windrbd_bootdevice.c \
		$(WINDRBD_SRCDIR)/windrbd_device.c $(WINDRBD_SRCDIR)/windrbd_drbd_url_parser.c $(WINDRBD_SRCDIR)/windrbd_module.c \
		$(WINDRBD_SRCDIR)/windrbd_netlink.c $(WINDRBD_SRCDIR)/windrbd_test.c $(WINDRBD_SRCDIR)/windrbd_threads.c \
		$(WINDRBD_SRCDIR)/windrbd_usermodehelper.c $(WINDRBD_SRCDIR)/windrbd_waitqueue.c \
		$(WINDRBD_SRCDIR)/windrbd_winsocket.c $(WINDRBD_SRCDIR)/windrbd_locking.c \
		$(WINDRBD_SRCDIR)/tiktok.c

all: versioninfo windrbd.sys

.PHONY: versioninfo
versioninfo:
	cd ../.. && ./versioninfo.sh converted-sources $(EXTRA_VERSION) || true

windrbd.sys: $(patsubst %.c,%.obj,$(DRBD_FILES)) $(patsubst %.c,%.obj,$(WINDRBD_FILES)) resource.res
	rm -f windrbd.pdb "_$@"
	$(VC) $(WIN_LINK_INPUT) $^ $(WIN_LDFLAGS) /PDB:"windrbd.pdb" /OUT:"_$@"
	mv -f "_$@" "$@"
	"$(EWDK_BIN)/inf2cat.exe" /driver:. /os:XP_X86,Vista_X86,Vista_X64,7_X86,7_X64,8_X86,8_X64,6_3_X86,6_3_X64,10_X86,10_X64
ifdef R
# Linbit DigiCert certificate (trusted by Microsoft)
	"$(EWDK_BIN)/signtool.exe" sign /fd SHA256 /v /ac "C:\cert\DigiCert High Assurance EV Root CA.crt" /a /t http://timestamp.digicert.com "$@"
# Thanks to David Grayson (http://www.davidegrayson.com/signing/#howto)
	"$(EWDK_BIN)/signtool.exe" sign /fd SHA256 /v /ac "C:\cert\DigiCert High Assurance EV Root CA.crt" /a /t http://timestamp.digicert.com windrbd.cat
else
# We need a self signed certificate which has to be added to the
# Windows certificate store in order to load the driver. See
# readme.txt file in the crypto directory to learn how to create it.

	"$(EWDK_BIN)/signtool.exe" sign /f ../../crypto/$(KEY).pfx /p $(PASSWD) /v "$@"
endif


resource.res: resource.rc
	"$(EWDK_BIN)/rc.exe" $<

ifeq ($(shell uname -o),Cygwin)
    %.obj: %.c
	rm -f "$(call fPDB,$<)"
	$(VC) $(WIN_CFLAGS) $(WIN_DEF_INCLUDES) "$<" /c /Fo:"$@" /Fd:"$(call fPDB,$<)"
# /Fi:"$(patsubst %.c,%.E,$<)" ...  cl : Command line warning D9007 : '/Fi:' requires '/P'; option ignored
	echo "-- $@ done --"

    %.E: %.c
	$(VC) $(WIN_CFLAGS) $(WIN_DEF_INCLUDES) "$<" /E > "$@"

endif

deps:
	gcc -D BITS_PER_LONG=64 -D _MSC_VER=1300 -D _WIN32=1 $(C_DEFINES) $(WIN_INCLUDE_DIRS) $(subst /FI,-include ,$(WIN_DEF_INCLUDES)) -M *.c ../../windrbd/src/*.c | perl -pe 's/^(\S+)\.o:/\1.obj \1.E:/' > Makefile.deps 

install:
	bash -c 'cwd=`pwd` ; /cygdrive/c/Windows/System32/InfDefaultInstall.exe `cygpath -w "$${cwd}"`\\windrbd.inf'

-include Makefile.deps

clean:
	rm -f *.obj *.pdb
	rm -f $(WINDRBD_SRCDIR)/*.obj $(WINDRBD_SRCDIR)/*.pdb
	rm -f windrbd.sys windrbd.cat

package: windrbd.sys
	( cd ../../inno-setup && iscc windrbd.iss /DWindrbdSource=$(WINDRBD_SOURCE) /DWindrbdUtilsSource=$(DRBD_UTILS_SOURCE) )
ifdef R
	( cd ../../inno-setup &&  "$(EWDK_BIN)/signtool.exe" sign /fd SHA256 /v /ac "C:\cert\DigiCert High Assurance EV Root CA.crt" /a /t http://timestamp.digicert.com install-`sed -e 's/[^"]*"\([^"]*\).*/\1/g' version.iss`.exe )
endif
	chmod a+x ../../inno-setup/install*.exe

